#include "stdafx.h"
#include "..\..\cz_def.h"
#include "..\..\function\cz_log.h"
#include "file_def.h"
#include "FixedSizeBinFileReader.h"
#include "FileReaderMapping.h"
#include "FileReaderPool.h"

FixedSizeBinFileReader::FixedSizeBinFileReader()
{
	Clear();
}

FixedSizeBinFileReader::~FixedSizeBinFileReader()
{
	Uninit();
}

bool FixedSizeBinFileReader::Init(IN stringc& strBinFile, IN u32 binUseMemory, IN u32 readFlag, IN u32 recordSize)
{
	Uninit();

	u32 reserveSpace;

	m_binUseMemory = binUseMemory;
	m_readFlag = readFlag;
	m_recordSize = recordSize;

	if (((m_readFlag & READ_FLAG_MAPPING) != 0) &&
		((m_readFlag & READ_FLAG_POOL) != 0)) m_readFlag &= ~READ_FLAG_MAPPING;
	if (((m_readFlag & READ_FLAG_MAPPING) == 0) &&
		((m_readFlag & READ_FLAG_POOL) == 0)) m_readFlag |= READ_FLAG_MAPPING;

	if ((m_readFlag & READ_FLAG_MAPPING) != 0)
	{
		m_pBinFile = new FileReaderMapping;
		if (m_pBinFile == NULL)
		{
			CZ_LOG_ERRORA("");
			goto L_Failed;
		}
	}
	else if ((m_readFlag & READ_FLAG_POOL) != 0)
	{
		m_pBinFile = new FileReaderPool;
		if (m_pBinFile == NULL)
		{
			CZ_LOG_ERRORA("");
			goto L_Failed;
		}
	}
	m_readFlag &= ~(READ_FLAG_MAPPING | READ_FLAG_POOL); 
	
	if ((m_readFlag & READ_FLAG_FORWARD) != 0) reserveSpace = 0;
	else if ((m_recordSize & READ_FLAG_BACKWARD) != 0) reserveSpace = recordSize;
	else reserveSpace = 0;

	if (!m_pBinFile->Init(strBinFile, m_binUseMemory, reserveSpace, m_readFlag))
	{
		CZ_LOG_ERRORA("");
		goto L_Failed;
	}
	m_binFileSize = m_pBinFile->GetFileSize();
	if ((m_binFileSize % m_recordSize) != 0)
	{
		CZ_LOG_ERRORA("");
		goto L_Failed;
	}
	m_recordNum = (u32)(m_binFileSize / m_recordSize);

	return true;

L_Failed:
	Uninit();
	return false;
}

void FixedSizeBinFileReader::Uninit()
{
	if (m_pBinFile != NULL)
	{
		m_pBinFile->Uninit();
		delete m_pBinFile;
	}

	Clear();
}

u32 FixedSizeBinFileReader::GetRecordNum()
{
	return m_recordNum;
}

u32 FixedSizeBinFileReader::GetRecordSize()
{
	return m_recordSize;
}

bool FixedSizeBinFileReader::GetRecordFromIndex(IN u32 index, OUT void* pRecord)
{
	u64 offset;
	_BIN_FILE_RESULT fr;

	if (index >= m_recordNum)
	{
		CZ_LOG_ERRORA("");
		return false;
	}

	offset = (u64)index * (u64)m_recordSize;

	fr = GetRecordFromOffset(m_pBinFile, offset, pRecord);
	if (fr != BIN_FILE_SUCCESS)
	{
		CZ_LOG_ERRORA("");
		return false;
	}

	return true;
}

void FixedSizeBinFileReader::Clear()
{
	m_binUseMemory = 0;
	m_readFlag = READ_FLAG_NULL;
	m_recordSize = 0;

	m_pBinFile = NULL;
	m_binFileSize = 0;

	m_recordNum = 0;
}

_BIN_FILE_RESULT FixedSizeBinFileReader::GetRecordFromOffset(INOUT FileReader* pfr, IN u64 offset, OUT void* pRecord)
{
	if (offset == m_binFileSize) return BIN_FILE_END;
	if (offset > m_binFileSize) return BIN_FILE_ERROR;

	if (pRecord != NULL)
	{
		if (!pfr->GetData(offset, (u8*)pRecord, m_recordSize)) return BIN_FILE_ERROR;
	}

	return BIN_FILE_SUCCESS;
}